#pragma once

#include "LogMessage.hpp"

#include <iostream>
#include <string>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <jsoncpp/json/json.h>

// 约定格式中的空格
#define SPACE " "
#define SPACE_LEN strlen(SPACE)

#define SEP "\r\n"
#define SEP_LEN strlen(SEP)


// 客户端发送请求，服务端接收
class Request
{
public:
    // 供服务端用的构造
    Request()
    {}

    // 供客户端用的构造
    Request(int x, int y, char op)
        : _x(x)
        , _y(y)
        , _op(op)
    {}
    
    // 序列化
    std::string SerializeRequest()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;

        Json::FastWriter writer;
        std::string res = writer.write(root);

        return res;
    }

    // 反序列化
    bool DeserializeRequest(const std::string& str)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = root["op"].asInt();

        return true;
    }

public:
        // 格式:_x _op _y
    int _x;
    int _y;
    char _op;
};

// 服务端回复数据，客户端接收
class Response
{
public:
    // 客户端用的构造
    Response()
        :_result(0)
        ,_code(0)
    {}

    // 服务端用的构造
    Response(int result, int code)
        : _result(result)
        , _code(code)
    {}

    // 序列化 _result _code
    std::string SerializeResponse()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        std::string res = writer.write(root);

        return res;
    }

    // 反序列化 _result _code
    bool DeserializeResponse(const std::string& str)
    {
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);

        _result = root["result"].asInt();
        _code = root["code"].asInt();

        return true;
    }

public:
    int _result; // 运算结果
    int _code; // 相当于错误码
};


// 接收数据
bool Recv(int sockfd, std::string& inBuff)
{
    char buff[1024];
    int ret = recv(sockfd, buff, sizeof(buff) - 1, 0);
    if(ret > 0)
    {
        buff[ret] = 0;
        inBuff += buff;
        LogMessage(DEBUG, _F, _L, "recv message ::%s", buff);
    }
    else if(ret == 0)
    {
        LogMessage(NORMAL, _F, _L, "disconnect from the opposite end");
        return false;
    }
    else
    {
        LogMessage(ERROR, _F, _L, "recv err");
        return false;
    }

    return true;
}

// 发送数据
void Send(int sockfd, const std::string& sendBuff)
{
    int ret = send(sockfd, sendBuff.c_str(), sendBuff.size(), 0);
    if(ret >= 0)
    {
        LogMessage(DEBUG, _F, _L, "send %s success", sendBuff.c_str());
    }
    else
    {
        LogMessage(ERROR, _F, _L, "send err %d:%s", errno, strerror(errno));
    }
}

// 对序列化后的字符串添加length\r\n 和 \r\n，对于
std::string Encode(const std::string &str)
{
    // 局部string对象
    std::string res;
    
    // 添加length
    res = std::to_string(str.size());

    // 添加第一个\r\n
    res += SEP;

    // 添加正文str
    res += str;

    // 添加最后的\r\n
    res += SEP;

    // 到这里res = length\r\nstr\r\n
    return res;
}

// 对接收到的字符串去掉length\r\n 和 \r\n
std::string Decode(std::string &str)/*这里的str是Recv读取到的inbuff，在这里读取出一个正文就去掉一个报文，Recv中还可以接着读*/
{
    // 局部string对象
    std::string res;
    
    // 以5\r\n1 + 2\r\n为例，
   /*下标01 2 345678 9*/
            // 如果是如果3\r\n5 0\r\r这种服务端发送的数据也可以正确执行

    // 先找到str中的第一个\r\n
    std::size_t pos = str.find(SEP);

    // 如果没找到，要么是不符合协议，要么是str中没有内容
    if(pos == std::string::npos) return "";

    // 读取到length的值
    size_t len = std::stoi(str.substr(0, pos)); // len为5

    // 提取出剩余一个正文长度
    size_t leftSize = str.size() - pos - 2 * SEP_LEN; // 1 + 2的长度
    if(leftSize < len) return ""; // 剩余正文长度不够len
    
    // 这里足够提取一个正文
        // 去掉length和第一个\r\n
    str.erase(0, pos + SEP_LEN); // 此处剩str下1 + 2\r\n
                                       //下标为012345 6 

    // 通过len拿到正文并将str中的正文和第二个\r\n
    res = str.substr(0, len);
    str.erase(0, len + SEP_LEN);

    // 此处res = 1 + 2，str去掉了一个完整报文
    return res;
}



// // 客户端发送请求，服务端接收
// class Request
// {
// public:
//     // 供服务端用的构造
//     Request()
//     {}

//     // 供客户端用的构造
//     Request(int x, int y, char op)
//         : _x(x)
//         , _y(y)
//         , _op(op)
//     {}
    
//     // 序列化
//     std::string SerializeRequest()
//     {
//         // 按照格式走
//         std::string res;
//         res += std::to_string(_x);
//         res += SPACE;
//         res += _op;
//         res += SPACE;
//         res += std::to_string(_y);

//         LogMessage(DEBUG, _F, _L, "client serialize %s success", res.c_str());
//         return res;
//     }

//     // 反序列化
//     bool DeserializeRequest(const std::string& str)
//     {
//         // 先找_op左边的空格
//         size_t leftSpace = str.find(SPACE);
//             // 没找到，格式错误
//         if(leftSpace == std::string::npos)
//         {
//             LogMessage(ERROR, _F, _L, "客户端发来的字符串中没有空格,格式错误");
//             return false;
//         }
//             // 找到了但是空格在最开头，没有_x，格式错误
//         if(leftSpace == 0)
//         {
//             LogMessage(ERROR, _F, _L, "客户端发来的字符串中没有左操作数,格式错误");
//             return false;
//         }

//         // 再找_op右边的空格
//         size_t rightSpace = str.rfind(SPACE);
//             // 走到找至少是有一个空格的，那么这里一定能找到一个空格
//                 // 如果右边的空格和左边的空格重合，格式错误
//         if(rightSpace == leftSpace)
//         {
//             LogMessage(ERROR, _F, _L, "客户端发来的字符串中没有操作符,格式错误");
//             return false;
//         }
//                 // 右边的空格在最结尾，没有_y，格式错误
//         if(rightSpace == str.size() - 1)
//         {
//             LogMessage(ERROR, _F, _L, "客户端发来的字符串中没有右操作数,格式错误");
//             return false;
//         }

//             // "1 + 2"为例leftSpace为1，right为3
//         // 开始反序列化
//         _x = std::stoi(str.substr(0, leftSpace)); // substr我就不介绍了，不懂的同学去cplusplus查查
//         _op = str[leftSpace + SPACE_LEN];
//         _y = std::stoi(str.substr(rightSpace + SPACE_LEN));
//         LogMessage(DEBUG, _F, _L, "server deserialize %s success", str.c_str());
//         return true;
//     }

// public:
//         // 格式:_x _op _y
//     int _x;
//     int _y;
//     char _op;
// };



// // 服务端回复数据，客户端接收
// class Response
// {
// public:
//     // 客户端用的构造
//     Response()
//         :_result(0)
//         ,_code(0)
//     {}

//     // 服务端用的构造
//     Response(int result, int code)
//         : _result(result)
//         , _code(code)
//     {}

//     // 序列化 _result _code
//     std::string SerializeResponse()
//     {
//         // 按格式走
//         std::string res;
//         res += std::to_string(_result);
//         res += SPACE;
//         res += std::to_string(_code);

//         LogMessage(DEBUG, _F, _L, "server serialize %s success", res.c_str());
//         return res;
//     }

//     // 反序列化 _result _code
//     bool DeserializeResponse(const std::string& str)
//     {
//         // 先找空格
//         size_t pos = str.find(SPACE);
//         if (pos == std::string::npos)
//         {
//             LogMessage(ERROR, _F, _L, "服务端发来的字符串中没有空格,格式错误");
//             return false;
//         }

//         if(pos == 0)
//         {
//             LogMessage(ERROR, _F, _L, "服务端发来的字符串中没有result,格式错误");
//             return false;
//         }

//         if(pos == str.size() - 1)
//         {
//             LogMessage(ERROR, _F, _L, "服务端发来的字符串中没有_code,格式错误");
//             return false;
//         }

//         // 解析
//         _result = atoi(str.substr(0, pos).c_str());
//         _code = atoi(str.substr(pos + SPACE_LEN).c_str());
//         LogMessage(DEBUG, _F, _L, "client deserialize %s success", str.c_str());
//         return true;
//     }

// public:
//     int _result; // 运算结果
//     int _code; // 相当于错误码
// };

